//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "FastaData.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define MAX_SIZE 500000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
FastaData::FastaData () {

  this->sequence = new String ();
  this->header   = new String ();
  this->toString = new String ();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
FastaData::FastaData (const FastaData& fastaData) {

  this->sequence = new String (fastaData.sequence);
  this->header   = new String (fastaData.header);
  this->toString = new String (fastaData.toString);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
FastaData::FastaData (const FastaData* fastaData) {

  this->sequence = new String (fastaData->sequence);
  this->header   = new String (fastaData->header);
  this->toString = new String (fastaData->toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
FastaData::~FastaData () {

  if (this->sequence) delete this->sequence;
  if (this->header)   delete this->header;
  if (this->toString) delete this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void FastaData::Sequence (String* sequence) {

  if (sequence)
    *(this->sequence) = *sequence;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void FastaData::Header (String* header) {

  if (header)
    *(this->header) = *header;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//

String* FastaData::Sequence (void) {

  return this->sequence;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* FastaData::Header (void) {

  return this->header;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool FastaData::ReadFromString (String* data) {

  if (!data || !data->Length()) return false;
  
  char   tmpData [data->Length() + 1];
  char*  lines = NULL;
  
  String header;
  
  strcpy(tmpData, data->Out());
  tmpData[data->Length()] = '\0';

  lines = strtok(tmpData, "\n");
  
  while (lines) {

    if      (lines[0] == '>') { this->header->In(lines + 1);   this->header->Trim();                        }
    else if (lines[0] != '>') { this->sequence->In(lines + 1); this->sequence->RTrim();              }
    
    lines = strtok(NULL, "\n");

  }
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool FastaData::ReadFromString (char* data) {

  if (!data) return false;
  
  String dataChar;
  dataChar.In(data);
  
  return this->ReadFromString(&dataChar);    

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* FastaData::ToString (void) {

  char buffer [MAX_SIZE + 1];
  
  sprintf(buffer, ">%s\n%s\0", this->header->Out(), this->sequence->Out());
  
  this->toString->In(buffer);
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
FastaData FastaData::operator= (const FastaData& fastaData) {

  *(this->sequence) = *(fastaData.sequence);
  *(this->header )  = *(fastaData.header);

  *(this->toString) = *(fastaData.toString);

  return *this;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
